﻿using System;
using System.Runtime.InteropServices;

namespace IupNET
{

    

    public class Control:IupBase
    {

        

        internal Control(IntPtr obj):base(obj)
        {
            
        }

        internal static Control FindControl(IntPtr obj)
        {
            IupBase res;
            if (allobjects.TryGetValue(obj, out res))
                return res as Control;
            return null;
        }

        


        /// <summary>
        /// Let us use this class as an argument directly to IUP functions
        /// </summary>
        public static implicit operator IntPtr(Control c)
        {
            if (c == null)
                return IntPtr.Zero;
            return c.cobject;
        }


        
        public bool Active
        {
            get
            {
                return GetAttribute("ACTIVE") == "YES";
            }
            set
            {
                SetAttribute("ACTIVE", value ? "YES" : "NO");
            }
        }

        public Color BgColor
        {
            get
            {
                return Convert.StringToColor(GetAttribute("BGCOLOR"));
            }
            set
            {
                SetAttribute("BGCOLOR", Convert.ColorToString(value));
            }
        }

        public Color FgColor
        {
            get
            {
                return Convert.StringToColor(GetAttribute("FGCOLOR"));
            }
            set
            {
                SetAttribute("FGCOLOR", Convert.ColorToString(value));
            }
        }

        public string Font
        { //TODO: maybe we should have easier font usage than strings?
            get
            {
                return GetAttribute("FONT");
            }
            set
            {
                SetAttribute("FONT", value);
            }
        }

        public bool Visible
        {
            get
            {
                return GetAttribute("VISIBLE") == "YES";
            }
            set
            {
                SetAttribute("VISIBLE", value ? "YES" : "NO");
            }
        }


        public Size2i ClientSize
        { 
            get
            {
                return Convert.StringToSize(GetAttribute("CLIENTSIZE"));
            }
            set
            {
                SetAttribute("CLIENTSIZE", Convert.SizeToString(value));
            }
        }

        public Expand Expand
        {
            get
            {
                return Convert.StringToExpand(GetAttribute("EXPAND"));
            }
            set
            {
                SetAttribute("EXPAND", Convert.ExpandToString(value));
            }
        }

        public bool Floating
        {
            get
            {
                return GetAttribute("FLOATING") == "YES";
            }
            set
            {
                SetAttribute("FLOATING", value ? "YES" : "NO");
            }
        }

        public string Name //note: not related to handle name
        {
            get
            {
                return GetAttribute("NAME");
            }
            set
            {
                SetAttribute("NAME", value);
            }
        }

        public Point2i Position
        { 
            get
            {
                return Convert.StringToPoint(GetAttribute("POSITION"));
            }
            set
            {
                SetAttribute("POSITION", Convert.PointToString(value,","));
            }
        }

        public Size2i RasterSize
        {
            get
            {
                return Convert.StringToSize(GetAttribute("RASTERSIZE"));
            }
            set
            {
                SetAttribute("RASTERSIZE", Convert.SizeToString(value));
            }
        }


        public Size2i Size
        {
            get
            {
                return Convert.StringToSize(GetAttribute("SIZE"));
            }
            set
            {
                SetAttribute("SIZE", Convert.SizeToString(value));
            }
        }

        public string Tip 
        {
            get
            {
                return GetAttribute("TIP");
            }
            set
            {
                SetAttribute("TIP", value);
            }
        }
        
        //TODO: many sub-tip attributes see iup help

        public string Title
        {
            get
            {
                return GetAttribute("TITLE");
            }
            set
            {
                SetAttribute("TITLE", value);
            }
        }

        public string Value //TODO: maybe this should be protected and used by typed properties in inherited
        {
            get
            {
                return GetAttribute("VALUE");
            }
            set
            {
                SetAttribute("VALUE", value);
            }
        }

        

        


       
        /// <summary>
        /// In Motif, returns the Widget handle.
        /// In Windows, returns the HWND handle.
        /// In GTK, return the GtkWidget* handle.
        /// 
        /// Verification-only attribute, available after the control is mapped.
        /// For elements that do not have a native representation, IntPtr.Zero is returned.
        /// </summary>
        public IntPtr NativeHandle
        {
            get
            {
                return Iupc.GetAttributePtr(cobject,"WID");
            }
        }

        public int X
        {
            get
            {
                return Convert.StringToInt(GetAttribute("X"));
            }
            set
            {
                SetAttribute("X", value.ToString());
            }
        }

        public int Y
        {
            get
            {
                return Convert.StringToInt(GetAttribute("Y"));
            }
            set
            {
                SetAttribute("Y", value.ToString());
            }
        }


        public IntPtr SetCallback(string name, IntPtr func)
        {
            return Iupc.SetCallback(cobject, name, func);
        }

        public IntPtr GetCallback(string name)
        {
            return Iupc.GetCallback(cobject, name);
        }

        public ZOrder ZOrder
        {

            set
            {
                if (value == ZOrder.Front)
                    SetAttribute("ZORDER", "FRONT");
                else
                    SetAttribute("ZORDER", "BACK");
            }
            get
            {
                string v = GetAttribute("ZORDER");
                if (v == "FRONT")
                    return ZOrder.Front;
                return ZOrder.Back;
            }
        }


        public string[] GetAllAttributes()
        {
            int numattrib = Iupc.GetAllAttributes(cobject, null, 0);
            IntPtr[] atts = new IntPtr[numattrib];
            string[] res=new string[numattrib];
            Iupc.GetAllAttributes(cobject, atts, numattrib);

            for (int l = 0; l < atts.Length; l++)
            {
                res[l] = Marshal.PtrToStringAnsi(atts[l]);
            }
            return res;            
        }


      
        

        public void Hide()
        {
            Iupc.Hide(cobject);
        }


        /// <summary>
        /// Updates the size and layout of controls after changing size attributes. 
        /// Can be used for any element inside a dialog, the layout of the dialog will be updated. 
        /// It can change the layout of all the controls inside the dialog because of the dynamic layout positioning. 
        /// </summary>
        public void Refresh()
        {
            Iupc.Refresh(cobject);
        }

        /// <summary>
        /// Mark the element or its children to be redraw when the control returns to the system.
        /// </summary>
        public void Update()
        {
            Iupc.Update(cobject);
        }

        /// <summary>
        /// Force the element and its children to be redraw immediately.
        /// </summary>
        public void Redraw(bool children)
        {
            Iupc.Redraw(cobject, children ? 1 : 0);
        }


        public Control Append(Control child)
        {
            return FindControl(Iupc.Append(cobject,child.cobject));
        }

        public void Detach()
        {
            Iupc.Detach(cobject);
        }

        public void Insert(Control ref_child,Control new_child)
        {
            Iupc.Insert(cobject,ref_child.cobject,new_child.cobject);
        }

        public Control Parent
        {
            get
            {
                return FindControl(Iupc.GetParent(cobject));
            }

            set
            {
                Iupc.Reparent(cobject, value.cobject);
            }
        }

        public Control GetChild(int pos)
        {
            return FindControl(Iupc.GetChild(cobject, pos));
        }

        public int GetChildPos(Control child)
        {
            return Iupc.GetChildPos(cobject, child.cobject);
        }

        public int ChildCount
        {
            get
            {
                return Iupc.GetChildCount(cobject);
            }
        }

        public Control GetNextChild(Control child) 
        {

            return FindControl(Iupc.GetNextChild(cobject, child == null ? IntPtr.Zero : child));
        }

        public Control Brother
        {
            get
            {
                return FindControl(Iupc.GetBrother(cobject));
            }
        }

        public Dialog Dialog
        {
            get
            {
                return FindControl(Iupc.GetDialog(cobject)) as Dialog;
            }
        }

        public Control NextField()
        {
            return FindControl(Iupc.NextField(cobject));
        }

        public Control PreviousField()
        {
            return FindControl(Iupc.PreviousField(cobject));
        }


        public Control SetFocus() {
            return FindControl(Iupc.SetFocus(cobject));
           
        }

        #region EVENT_CALLBACKS



        public EventCallback MapCB
        {
            get {
                return CBHandler.Fetch("MAP_CB");
            }
            set {
                CBHandler.Set("MAP_CB", value);
            }
        }

        public EventCallback UnMapCB
        {
            get
            {
                return CBHandler.Fetch("UNMAP_CB");
            }
            set
            {
                CBHandler.Set("UNMAP_CB", value);
            }
        }

        public EventCallback GetFocusCB
        {
            get
            {
                return CBHandler.Fetch("GETFOCUS_CB");
            }
            set
            {
                CBHandler.Set("GETFOCUS_CB", value);
            }
        }

        public EventCallback KillFocusCB
        {
            get
            {
                return CBHandler.Fetch("KILLFOCUS_CB");
            }
            set
            {
                CBHandler.Set("KILLFOCUS_CB", value);
            }
        }

        public EventCallback EnterWindowCB
        {
            get
            {
                return CBHandler.Fetch("ENTERWINDOW_CB");
            }
            set
            {
                CBHandler.Set("ENTERWINDOW_CB", value);
            }
        }

        public EventCallback LeaveWindowCB
        {
            get
            {
                return CBHandler.Fetch("LEAVEWINDOW_CB");
            }
            set
            {
                CBHandler.Set("LEAVEWINDOW_CB", value);
            }
        }

        public EventCallback KAny
        {
            get
            {
                return CBHandler.Fetch("K_ANY");
            }
            set
            {
                CBHandler.Set("K_ANY", value);
            }
        }
            
        public EventCallback HelpCB {
            get
            {
                return CBHandler.Fetch("HELP_CB");
            }
            set
            {
                CBHandler.Set("HELP_CB", value);
            }
        }
            


        #endregion


    }

    public enum ZOrder
    {
        Front,
        Back
    }
}
